package com.wlyuan.open.scanner.service;

import com.alibaba.fastjson.JSON;
import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.open.dto.OpenSearchSourceDataDTO;
import com.wlyuan.open.dto.incr.IncrSourceDTO;
import com.wlyuan.open.dto.incr.IncrTenantDTO;
import com.wlyuan.open.dto.incr.IncrTenantNameDTO;
import com.wlyuan.open.scanner.application.factory.IncrSyncHandler;
import com.wlyuan.open.scanner.application.factory.ScannerHandlerFactory;
import com.wlyuan.open.scanner.application.task.bill.BillTaskHandler;
import com.wlyuan.open.scanner.application.task.combine.CombineTaskHandler;
import com.wlyuan.open.scanner.application.task.consignee.ConsigneeTaskHandler;
import com.wlyuan.open.scanner.application.task.goods.GoodsTaskHandler;
import com.wlyuan.open.scanner.application.task.order.OrderTaskHandler;
import com.wlyuan.open.scanner.application.task.pay.PayTaskHandler;
import com.wlyuan.open.scanner.application.task.quotation.CombineQuotationTaskHandler;
import com.wlyuan.open.scanner.application.task.quotation.QuotationTaskHandler;
import com.wlyuan.open.scanner.application.task.top.TopTaskHandler;
import com.wlyuan.open.scanner.application.task.transport.TransportRelationTaskHandler;
import com.wlyuan.open.scanner.application.task.transport.TransportTaskHandler;
import com.wlyuan.open.scanner.constant.ScannerCodeEnum;
import com.wlyuan.open.scanner.exception.ValueErrorException;
import com.wlyuan.open.scanner.feign.OpenPlatformFeignInvoker;
import com.wlyuan.open.scanner.repository.TemplateRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Optional;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ScannerService {
    private final BillTaskHandler billTaskHandler;
    private final PayTaskHandler payTaskHandler;
    private final TemplateRepository templateRepository;
    private final OpenPlatformFeignInvoker openPlatformFeignInvoker;
    private final TransportTaskHandler transportTaskHandler;
    private final OrderTaskHandler orderTaskHandler;
    private final GoodsTaskHandler goodsTaskHandler;
    private final ConsigneeTaskHandler consigneeTaskHandler;
    private final CombineTaskHandler combineTaskHandler;
    private final TransportRelationTaskHandler transportRelationTaskHandler;
    private final TopTaskHandler topTaskHandler;
    private final QuotationTaskHandler quotationTaskHandler;
    private final CombineQuotationTaskHandler combineQuotationTaskHandler;

    /**
     * 全量扫描
     *
     * @param name
     */
    @Async("asyncExecutor")
    public void scanner(String name) {
        Arrays.asList(name.split(",")).forEach(x -> {
            var scannerCodeEnum = ScannerCodeEnum.fromName(x);
            AssertUtils.assertNotNull(scannerCodeEnum, new ValueErrorException("未找到对应类型"));
            logger.info("************************************************************");
            logger.info("开始全量同步新系统 {} 数据", scannerCodeEnum.getName());
            ScannerHandlerFactory.getHandler(scannerCodeEnum.getVal()).scanner();
        });
    }

    /**
     * 全量收货方
     */
    @Async("asyncExecutor")
    public void scannerConsignee() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.CONSIGNEE.getName());
        consigneeTaskHandler.handler(null);
    }

    /**
     * 全量合约
     */
    @Async("asyncExecutor")
    public void scannerTemplate() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.TEMPLATE.getName());
        templateRepository.sync();
    }

    /**
     * 全量报价
     */
    @Async("asyncExecutor")
    public void scannerQuotation() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.QUOTATION.getName());
        quotationTaskHandler.handler(null);
    }


    /**
     * 全量物品
     */
    @Async("asyncExecutor")
    public void scannerGoods() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.GOODS.getName());
        goodsTaskHandler.handler(null);
    }

    /**
     * 全量订单
     */
    @Async("asyncExecutor")
    public void scannerOrder() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.ORDER.getName());
        orderTaskHandler.handler(null);
    }

    /**
     * 全量运单单
     */
    @Async("asyncExecutor")
    public void scannerTransport() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.TRANSPORT.getName());
        transportTaskHandler.handler(null);
    }

    /**
     * 全量运单单
     */
    @Async("asyncExecutor")
    public void scannerTransportRelation() {
        logger.info("************************************************************");
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.TRANSPORT_RELATION.getName());
        transportRelationTaskHandler.handler(null);
    }

    /**
     * 全量拼车单
     */
    @Async("asyncExecutor")
    public void scannerCombine() {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.COMBINE.getName());
        combineTaskHandler.handler(null);
    }

    /**
     * 全量同步对账单
     */
    @Async("asyncExecutor")
    public void syncBill() {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.BILL.getName());
        billTaskHandler.handler(null);
    }

    /**
     * 全量同步收付款
     */
    @Async("asyncExecutor")
    public void syncPay() {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.PAY.getName());
        payTaskHandler.handler(null);
    }

    @Async("asyncExecutor")
    public void syncPayType(Integer type) {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.PAY.getName());
        payTaskHandler.handlerType(type);
    }

    /**
     * 全量同步top扩展
     */
    @Async("asyncExecutor")
    public void syncTopExtension() {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.TOP_EXTENSION.getName());
        topTaskHandler.handler(null);
    }

    /**
     * 全量同步top扩展
     */
    @Async("asyncExecutor")
    public void syncCombineQuotation() {
        logger.info("开始全量同步新系统 {} 数据", ScannerCodeEnum.COMBINE_QUOTATION.getName());
        combineQuotationTaskHandler.handler(null);
    }

    /**
     * 增量扫描
     */
    public void increment(String name, String sourceId) {
        var scannerCodeEnum = ScannerCodeEnum.fromName(name);
        AssertUtils.assertNotNull(scannerCodeEnum, new ValueErrorException("未找到对应扫描类型 : " + name));
        logger.info("开始增量同步新系统 {} 数据", scannerCodeEnum.getName());
        Arrays.asList(sourceId.split(",")).parallelStream().forEach(id -> {
            IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).increment(Long.valueOf(id));
        });
    }

    /**
     * 增量扫描
     */
    public void increment(IncrSourceDTO source) {
        var scannerCodeEnum = ScannerCodeEnum.fromName(source.getName());
        AssertUtils.assertNotNull(scannerCodeEnum, new ValueErrorException("未找到对应扫描类型 : " + source.getName()));
        logger.info("开始增量同步新系统 {} 数据", scannerCodeEnum.getName());
        Arrays.asList(source.getSourceId().split(",")).parallelStream().forEach(id -> {
            IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).increment(Long.valueOf(id));
        });
    }

    /**
     * 根据租户增量
     */
    @Async("asyncExecutor")
    public void incrByTenant(IncrTenantDTO source) {
        var scannerCodeEnum = ScannerCodeEnum.fromName(source.getName());
        AssertUtils.assertNotNull(scannerCodeEnum, new ValueErrorException("未找到对应扫描类型 : " + source.getName()));
        logger.info("开始增量同步新系统 {} 数据，租戶id {}", scannerCodeEnum.getName(), source.getTenant());
        Arrays.asList(source.getTenant().split(",")).forEach(id -> {
            IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).incrByTenantId(Long.valueOf(id));
        });
    }

    @Async("asyncExecutor")
    public void incrByTenantName(IncrTenantNameDTO source) {
        Arrays.asList(source.getName().split(",")).forEach(name -> {
            var scannerCodeEnum = ScannerCodeEnum.fromName(name);
            if (!Optional.ofNullable(scannerCodeEnum).isPresent()) {
                logger.error("找不到实现类：{}", name);
                return;
            }
            logger.info("开始增量同步新系统 {} 数据，租戶id {}", scannerCodeEnum.getName(), source.getTenant());
            Arrays.asList(source.getTenant().split(",")).forEach(id -> {
                IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).incrByTenantId(Long.valueOf(id));
            });
        });
    }

    @Async("asyncExecutor")
    public void incrFail(OpenSearchSourceDataDTO source) {
        var scannerCodeEnum = ScannerCodeEnum.fromSourceClass(source.getSourceClass());
        AssertUtils.assertNotNull(scannerCodeEnum, new ValueErrorException("未找到对应扫描类型 : " + source.getSourceClass()));
        var result = openPlatformFeignInvoker.fail(source);
        logger.info("获取失败数据结果：{}", JSON.toJSON(result));
        if (result.success() && !CollectionUtils.isEmpty(result.getData())) {
            logger.info("{}失败的数量：{}", scannerCodeEnum.getName(), result.getData().size());
            result.getData().parallelStream().forEach(id -> {
                IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).increment(Long.valueOf(id));
            });
            logger.info("{}失败数据同步完成", scannerCodeEnum.getName());
        }
    }

    @Async("asyncExecutor")
    public void time(Long tenantId, String name, String startTime, String endTime) {
        try {
            Arrays.asList(name.split(",")).forEach(item -> {
                var scannerCodeEnum = ScannerCodeEnum.fromName(item);
                logger.info("开始根据创建时间增量同步新系统 {} 数据", scannerCodeEnum.getName());
                IncrSyncHandler.getEventListener(scannerCodeEnum.getVal()).incrByTime(tenantId, startTime, endTime);
            });
            logger.info("根据创建时间同步完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
